#ifndef __ZHONG_FACTORY__
#define __ZHONG_FACTORY__
#include <string>
#include <memory>  // std::auto_ptr
#include <cstdlib> // std::exit
#include <sstream>
#include <exception>

#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include <sw/redis++/redis.h>
#include "logger.hpp"
#include "elasticer.hpp"

namespace bite_im
{
    // odb-mysql数据库对象智能指针
    using DBPtr = std::shared_ptr<odb::core::database>;
    // redis对象智能指针
    using RedisPtr = std::shared_ptr<sw::redis::Redis>;
    // using DBPtr = std::shared_ptr<odb::mysql::database>;
    class ODBFactory
    {
    public:
        static DBPtr create(const std::string &user_name,
                            const std::string &password,
                            const std::string &db_name,
                            const std::string &host,
                            int port,
                            const std::string &cset,
                            int conn_pool_num)
        {
            // 1.构造连接池工厂对象---只能用并且必须用unique_ptr
            std::unique_ptr<odb::mysql::connection_pool_factory> cpf(new odb::mysql::connection_pool_factory(conn_pool_num, 0));
            // 2.构造数据库操作对象
            auto ret = std::make_shared<odb::mysql::database>(user_name,
                                                              password,
                                                              db_name, host, port, "", cset, 0, std::move(cpf));
            return ret;
        }
    };

    class RedisFactory
    {
    public:
        static RedisPtr create(const std::string &server_ip, int server_port, bool keep_alive, int db_flag)
        {
            sw::redis::ConnectionOptions opts;
            opts.host = server_ip;
            opts.port = server_port;
            opts.db = db_flag;
            opts.keep_alive = keep_alive;
            auto ret = std::make_shared<sw::redis::Redis>(opts);
            return ret;
        }
    };

    class ElasticFactory
    {
    public:
        // host_list 形式{"http://127.0.0.1:9200/", ...};
        static ElasticPtr create(const std::vector<std::string> &host_list)
        {
            auto client = std::make_shared<elasticlient::Client>(host_list);
            return client;
        }
    };
}

#endif